import CmdNo,string,regsub
from etgui import *

# constants...
gTabSheetStyle=EnvGetBool("GUI.Tools.Prefs.TabSheetStyle",1) # 0 = section layout style, 1 = tab sheet layout style
								# e.g. for file types and platforms view
gPointSectionGap=gPoint8		# gap between two sections in one page
gPointBorderGap=gPoint4		# gap between margin and content
gTextFieldLen=20				# also used for FileSelector and DirSelector
gBorderStyle=0					# 0 = separator layout style, 1 = border layout style
gFieldLayout=eVObjHFixed		# layout for ActionButtons and PopupButtons
gTabsPageSelectorOnTop=1		# layout for TabSheet page selectors
gScrollerSize=Point(150,125)	# minimal size of Scrollers in Collection Views
 
 
def MakeHeader(title,help,content): 
	"""Make header for page"""
	box= VBox(
		align=eVObjHExpand|eVObjVExpand,
		items=[
			Matte(
				Point(8,0),
				AlignBox(eVObjHExpand,
					flags=eVObjVFixed,
					inner=HBox(
						align=eVObjHExpand,
						flags=eVObjVFixed,
						items=[
							AlignBox(eVObjHLeft,MultilineTextItem("@B"+title+"@B")),
							AlignBox(eVObjHRight,TextItem(help)),
						]
					),
					ink=RGBInk(128,128,128),
				)
			),
			Matte(
				gPoint8,
				content
			)
		]
	)
	# XXX MSA TBD GetHelpID
	title=string.lower(title)
	title=regsub.gsub(' +','_',title)
	title=regsub.gsub('[^a-z0-9_]','',title)
#	print box
#	box.SetHelpID(title)
	return box
 
def MakeDialogWithButtons(panel,*buttons): 
	return Matte(
		gPointBorderGap,
		VBox(
			align=eVObjVExpand|eVObjHExpand,
			items=[
				VExpander(
					items= (
						panel,
						Filler(gPointBorderGap),
						AlignBox(
							eVObjHRight,
							flags=eVObjVFixed,
							inner=HBox(
								align=eVObjVBase|eVObjHEqual,
								items= buttons
							)
						)
					)
				)
			]
		)
	)
 
def MakeDialogInner(panel,*buttons): 
	"""Make margin for page"""
	catlabel=TextItem("Category:")
	catlabel.SetFlag(eVObjVFixed)
	return Matte(
		gPointBorderGap,
		VBox(
			align=eVObjVExpand|eVObjHExpand,
			items=[
				catlabel,
				VExpander(
					items= (
						panel,
						Filler(gPointBorderGap),
						AlignBox(
							eVObjHRight,
							flags=eVObjVFixed,
							inner=HBox(
								align=eVObjHExpand|eVObjVBase|eVObjHEqual,
								items= buttons
							)
						)
					)
				)
			]
		)
	)
class Sections:
	pass
class NamedSection:
	def __init__(self,name,*items):
		self.name=name
		self.items=tuple(filter(None,items))
def TabSheetOrPageLayout(align,*items):
	items=filter(None,items)
	if gTabSheetStyle:
		tabsheets=[]
		for i in items:
			tabsheets.append(
				TabPage(
					i.name,
					MakePageLayout(
						align,
						apply(MakeSectionLayout,i.items)
					)
				)
			)
		return apply(MakeTabSheetLayout,tuple(tabsheets))
	else:
		sections=[]
		for i in items:
			sections.append(
				apply(MakeBorderedSectionLayout,(i.name,)+i.items)
			)
		return apply(MakePageLayout,(align,)+tuple(sections))
def MakePageLayout(align,*pageItems): 
	"""Align page content"""
	pageItems=filter(None,pageItems)
	return AlignBox(
		align,
		VBox(
			align=eVObjHExpand|eVObjVExpand,
			gap=gPointSectionGap,
			items= pageItems
		)
	)

def MakeSectionLayout(*sectionItems): 
	"""Align section content"""
	sectionItems=filter(None,sectionItems)
	return Matte(
		gPointBorderGap,
		VBox(
			align=eVObjHExpand|eVObjVExpand,
			items= sectionItems
		)
	)

def MakeBorderedSectionLayoutWithAlign(header,align,items): 
	"""Align bordered section content"""
	sectionItems=filter(None,items)
	return BorderItem(
		MultilineTextItem(header),   # or: MultilineTextItem('@I'+'   '+header+'   '+'@I')
		Matte(
			gPointBorderGap,
			VBox(
				align=align,
				items= items
			)
		),
		gBorderStyle
	)
def MakeBorderedSectionLayout(header,*sectionItems): 
	"""Align bordered section content"""
	return MakeBorderedSectionLayoutWithAlign(header,eVObjHExpand,sectionItems)

def MakeTabSheetLayout(*pageItems):
	"""Align tab sheets content"""
	pageItems=filter(None,pageItems)
	return TabSheet(
		single_line=1,
		on_top=gTabsPageSelectorOnTop,
		items=pageItems
	)
 
def MakeListEditorLayout(listeditor,scrollersize=gScrollerSize,listheader=None):
	"""Align list editors content"""
	cv=listeditor.MakeCollView(scrollersize)
	cv.SetHelpID("collview")
	if listheader:
		cv=VBox(
			align=eVObjHExpand|eVObjVExpand,
			items=[
				listheader,
				cv
			]
		)
	buttons=listeditor.MakeButtons()
	bb=AlignBox(
			align=eVObjVCenter,
			flags=eVObjHFixed,
			inner=VBox(
				align=eVObjHExpand|eVObjVCenter,
				items=buttons
			)
		)
	bb.SetHelpID("buttons");
	return HBox(
		align=eVObjHExpand|eVObjVExpand,
		items=[
			cv,
			bb
		]
	)
 
def MakeModelDictEditorLayout(editor,useVerticalAlignment=1,header=None,border=gBorderStyle,merge_options=None,scroller_size=gScrollerSize):
	"""Aling model dict editors content"""
	preview=editor.MakePreview()
	listheader=None
	if header=="Corresponding Command":   # for file types context menu
		prev=MakeSectionLayout(MultilineTextItem(header),preview)
		listheader=MultilineTextItem("Command Label")
	elif header=="Command Specification":   # for vcs
		prev=MakeSectionLayout(MultilineTextItem(header),preview)
		listheader=MultilineTextItem("Command")
	elif header:
		prev=BorderItem(
			MultilineTextItem(header),
			Matte(
				gPointBorderGap,
				VBox(
					align=eVObjHExpand,
					items=[preview]
				)
			),
			border
		)
	else:
		prev=MakeSectionLayout(preview)
	listview=MakeListEditorLayout(editor,scroller_size,listheader)
 
	# make the item list
	items=[]
	items.append(MakeSectionLayout(listview))
	if merge_options:
		items.append(merge_options)
	items.append(prev)
	if useVerticalAlignment:
		box= VBox(
			align=eVObjHExpand|eVObjVExpand,
			gap=gPointSectionGap,
			items=items
		)
	else:
		box= HBox(
			align=eVObjHExpand|eVObjVExpand,
			gap=gPointSectionGap,
			items=items
		)
	if editor.SetDefaults is not None:
		box=NoMarkButtons(PotGuiVObjDefaultDecorator,"?",box,editor.SetDefaults)
	if hasattr(editor,"Open"):
		box=OpenDecorator(box,editor.Open)
	return box

def MakeCollViewLayout(controler,items,useActionButtons=0,useVerticalAlignmet=0,useToggleItems=0):
	"""Align collection view content"""
	sq=OrdCollection()
	controler.SetCollection(sq)
	for i,j in items:
		if useToggleItems:
			item=ToggleButton(-1,"%s" % i)   # XXX toggling of buttons does not work correct
		else:
			item=TextItem("%s" % i)
		sq.Add(item)
	cv=CollectionView(controler.Control,sq)
	cv.SelectItem(0)
	label="Edit.."
	if gTabSheetStyle:
		label="Properties..."
	if useActionButtons:
		collview=HBox(
			align=eVObjHExpand|eVObjVExpand,
			items=[
				Scroller(cv,gScrollerSize),
				AlignBox(
					align=eVObjVCenter,
					flags=eVObjHFixed,
					inner=VBox(
						align=eVObjHFixed|eVObjVCenter,
						items=[
							ActionButton(label,action=controler.EditSelected), # XXX control is missing
							ActionButton("Delete",action=controler.DeleteSelected),
							ActionButton("New..."),
							ActionButton("Copy..")
						]
					)
				)
			]
		)
	else:
		collview=Scroller(cv,gScrollerSize)
 
	preview=controler.GetPreview()
	if preview:
		if useVerticalAlignmet:
			return VBox(
				align=eVObjHExpand|eVObjVExpand,
				gap=gPointSectionGap,
				items=[
					MakeSectionLayout(collview),
					MakeSectionLayout(preview)
				]
			)
		else:
			return HBox(
				align=eVObjHExpand|eVObjVExpand,
				gap=gPointSectionGap,
				items=[
					MakeSectionLayout(collview),
					MakeSectionLayout(preview)
				]
			)
	else:
		return MakeSectionLayout(collview)

def MakeFieldLayout(field,align=gFieldLayout):
	"""Align ActionButtons and PopupButtons"""
	field.SetFlag(gFieldLayout)
	return field

def FieldWithButtonLayout(field,button,button1=None):
	"""Button associated with field"""
	button.SetFlag(eVObjHFixed)
	items=[field,button]
	if button1:
		button1.SetFlag(eVObjHFixed)
		items.append(button1)
	return HBox(
		align=eVObjVBase|eVObjHExpand,
		items=items
	)

def FieldWithButton(label,field,action=None):
	"""Button associated with field"""
	button=ActionButton(label,action=action)
	return FieldWithButtonLayout(field,button)

def PotTextField(label,update=0,width=gTextFieldLen,tooltip=None):
	"""New standard TextField"""
	tf=TextField(-1,width)
	obj= PotGuiTextField(label,tf,update)
	if tooltip:
		AddToolTip(tf,tooltip)
	return obj
def PasswordField(label,width=10,tooltip=None):
	"""New standard Password input Field"""
	tf=TextField(-1,width,Font(gSysFont.Fid(),gSysFont.Size(),gSysFont.Face()|eFacePassword))
	obj= PotGuiTextField(label,tf)
	if tooltip:
		AddToolTip(tf,tooltip)
	return obj


def PotExpandedTextField(model,label):
	"""TextField where pathes are represented expanded in the tooltip"""
	tt=TextItem("")
	tf= PotTextField(label,1,gTextFieldLen,tooltip=tt)
	model.AddModelObserver(ExpandedPathToolTip(tt,label),label,tf)
	return tf
 
def AdvancedButton(action=None,label="Advanced..."):
	"""New advanced ActionButton for starting of dialogs"""
	return MakeSectionLayout(
		MakeFieldLayout(ActionButton(label,action=action),eVObjHFixed|eVObjHRight)
	)

def MakeOkCancelDialog(title,model,view,*items):
	if not items:
		items=(
			ActionButton(CmdNo.cIdOk,"OK",default=1),
			ActionButton(CmdNo.cIdCancel,"Cancel")
		)
	inner= Matte(
		gPointBorderGap,
		VExpander(
			items= (
				view,
				Filler(gPointBorderGap),
				AlignBox(
					eVObjHCenter,
					flags=eVObjVFixed,
					inner=HBox(
						align=eVObjHExpand|eVObjVBase|eVObjHEqual,
						items=items
					)
				)
			)
		)
	)
	dialog=PotGuiDialog(
		model,
		inner,
		title,
		eWinBlock
	)
	return dialog

class SubDialog:
	def __init__(self,model,title):
		self.title=title
		self.model=model
		self.dialog=None
	def MakeDialog(self,model):
		inner=self.MakeDialogInner(model)
		return MakeOkCancelDialog(self.title,model,inner)
	def MakeDialogInner(self,model):
		raise RuntimeError, "Abstract Method"
	def BeforeShow(self):
		pass
	def AfterShow(self):
		pass
	def Show(self):
		if self.dialog is None:
			self.dialog=self.MakeDialog(self.model)
		self.BeforeShow()
		self.dialog.ShowUnderMouse()
		self.AfterShow()
	def __call__(self):
		self.Show()
def ShowSubDialog(title,model,view):
	dialog=MakeOkCancelDialog(title,model,view)
	return dialog.ShowUnderMouse()==CmdNo.cIdOk
	# do/undo manipulation of model

class FieldEnabler:
	"""A class implementing the enable/disable functionality"""
	def __init__(self,model,slot,items):
		self.slot=slot
		self.items=items
		if items:
			model.AddModelObserver(self,slot)
		self.__call__(model,slot)
	def __call__(self,model,slot):
		enable=self.IsEnabled(Cast(model).GetValue(self.slot))
		for item in self.items:
			item.Enable(enable)
	def IsEnabled(self,value):   # override if you want a different semantic
		if value:
			return 1
		return 0

class InverseFieldEnabler(FieldEnabler):
	def IsEnabled(self,value):
		return value==0

class FieldToolTip:
	def __init__(self,item,path,sep=' '):
		self.item=item
		self.path=path
		self.sep=sep
	def __call__(self,model,slot):
		model=Cast(model)
		s=model.GetValue(self.path)
		if s is None:
			s=""
		if type(s) is StringType:
			s=string.strip(s)
			if self.sep== ' ':
				s=string.splitfields(s) # use special ' ' split semantics
			else:
				s=string.splitfields(s,self.sep)
		self.item.SetString('TT'+string.joinfields(s,'\n'))

class ExpandedPathToolTip:
	def __init__(self,item,path):
		self.item=item
		self.path=path
	def __call__(self,model,slot):
		model=Cast(model)
		s=model.GetValue(self.path)
		expand=gSystem.GetExpandedPathName(str(s))
		self.item.SetString(str(expand))
 
class GenerateButton:
	"""Button for generating something e.g. GenIncludeMacro"""
	def __init__(self,model,path,name):
		self.model=model
		self.path=path
		self.name=name
	def DoGenerate(self):
		self.model.SetValue(self.path,self.model.GetValue(self.name))

class ModelIO:
	"""A class that does model IO.
 
	Associate Load with a load button and
	Associate Save with a save button.
	"""
	def __init__(self,model):
		try:
			self.model=Cast(model,"SimplePotGuiModel")
		except:
			self.model=None
	def Load(self):
		if not self.model:
			return
		file=SelectFile("Pot Input File",eFDRead)
		if file:
			f=open(file)
			data=f.read()
			f.close()
			self.model.UnDumpModel(data)
	def Save(self):
		if not self.model:
			return
		file=SelectFile("Pot Output File",eFDWrite)
		if file:
			data=self.model.DumpModel()
			f=open(file,'w')
			f.write(data)
			f.close()
 
